package com.linkhub.oms.common.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.comparator.PinyinComparator;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description: Stream转换工具类
 * @Author: echo
 * @Date: 2024/3/2 21:29
 * @Version: 1.0
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class QtStreamUtil {

    /**
     * 将List转成指定Key,Value的Map
     *
     * @param list     list
     * @param keyField key
     * @param value    value
     * @return Map
     */
    public static <T, K, V> Map<K, V> toMap(List<T> list,
                                            Function<? super T, ? extends K> keyField,
                                            Function<? super T, ? extends V> value) {
        if (CollUtil.isEmpty(list)) {
            return Maps.newHashMapWithExpectedSize(0);
        }

        return list.stream().collect(Collectors.toMap(keyField, value, (o1, o2) -> o2));
    }

    /**
     * 将List转成指定Key,Value的Map
     *
     * @param list     list
     * @param keyField key
     * @return Map
     */
    public static <T, K> Map<K, T> toMap(List<T> list, Function<? super T, ? extends K> keyField) {
        if (CollUtil.isEmpty(list)) {
            return Maps.newHashMapWithExpectedSize(0);
        }

        return list.stream().collect(Collectors.toMap(keyField, Function.identity(), (o1, o2) -> o1));
    }

    /**
     * 将List转成指定Key,Value的Map
     *
     * @param list     list
     * @param keyField key
     * @param value    value
     * @return Map
     */
    public static <T, K, V> Map<K, V> toLinkedHashMap(List<T> list,
                                                      Function<? super T, ? extends K> keyField,
                                                      Function<? super T, ? extends V> value) {
        if (CollUtil.isEmpty(list)) {
            return Maps.newHashMapWithExpectedSize(0);
        }

        return list.stream().collect(Collectors.toMap(keyField, value, (o1, o2) -> o2, LinkedHashMap::new));
    }

    /**
     * 将List转成指定Key,Value的Map
     *
     * @param list     list
     * @param keyField key
     * @return Map
     */
    public static <T, K> Map<K, T> toLinkedHashMap(List<T> list,
                                                   Function<? super T, ? extends K> keyField) {
        if (CollUtil.isEmpty(list)) {
            return Maps.newHashMapWithExpectedSize(0);
        }

        return list.stream().collect(Collectors.toMap(keyField, Function.identity(), (o1, o2) -> o1, LinkedHashMap::new));
    }

    /**
     * 抽取对象中的某个属性
     *
     * @param list     对象集合
     * @param keyField 属性
     * @param <T>      对象类型
     * @param <K>      属性类型
     * @return 属性值集合
     */
    public static <T, K> List<K> extractFieldList(Collection<T> list, Function<T, K> keyField) {
        if (CollUtil.isEmpty(list)) {
            return Lists.newArrayListWithCapacity(0);
        }

        return list.stream().map(keyField).collect(Collectors.toList());
    }

    /**
     * 抽取集合对象中的某个属性，指定最终生成的集合类型
     *
     * @param collection 对象集合
     * @param keyField   转换属性
     * @param supplier   集合生成lambda
     * @param <T>        实体类
     * @param <K>        属性类型
     * @param <C>        集合类型
     * @return collection及以下
     */
    public static <T, K, C extends Collection<K>> C extractFieldCollection(Collection<T> collection,
                                                                           Function<T, K> keyField,
                                                                           Supplier<C> supplier) {
        if (CollUtil.isEmpty(collection)) {
            return supplier.get();
        }

        return collection.stream().map(keyField).collect(Collectors.toCollection(supplier));
    }

    /**
     * 抽取Map中对象中的某个属性
     *
     * @param map         map
     * @param valueMapper 值转换
     * @param <K>         key
     * @param <V>         value
     * @param <T>         转换后的类型
     * @return map
     */
    public static <K, V, T> Map<K, T> extractFieldMap(Map<K, V> map, Function<? super Map.Entry<K, V>, ? extends T> valueMapper) {
        if (CollUtil.isEmpty(map)) {
            return Maps.newHashMap();
        }

        return map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, valueMapper));
    }

    /**
     * 通过指定条件过滤
     *
     * @param list      待过滤集合
     * @param predicate 过滤条件
     * @return 已过滤集合
     */
    public static <T> List<T> filter(Collection<T> list, Predicate<T> predicate) {
        if (CollUtil.isEmpty(list)) {
            return Lists.newArrayList();
        }

        return list.stream()
                .filter(predicate)
                .collect(Collectors.toList());
    }

    /**
     * 根据对象的属性去重
     *
     * @param list         原列表
     * @param keyExtractor 属性映射
     * @param <T>          对象类型
     * @return 去重后的列表
     */
    public static <T> List<T> distinct(Collection<T> list, Function<? super T, Object> keyExtractor) {
        return list.stream().filter(distinctByKey(keyExtractor)).collect(Collectors.toList());
    }

    /**
     * 将对象put到map中，如果map已存在该对象，则Predicate的结果为false，否则为true
     *
     * @param keyExtractor 被比较的对象
     * @param <T>          对象类型
     * @return 比对结果
     */
    private static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> map = Maps.newConcurrentMap();
        return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    /**
     * 根据对象的任一属性去重
     *
     * @param list          原列表
     * @param keyExtractors 属性映射列表
     * @param <T>           对象类型
     * @return 去重后的列表
     */
    public static <T> List<T> anyDistinct(Collection<T> list, Function<T, Object>... keyExtractors) {
        return list.stream().filter(anyDistinctByKey(keyExtractors)).collect(Collectors.toList());
    }

    /**
     * 具体去重判断
     *
     * @param functions 被比较的对象属性列表
     * @param <T>       对象类型
     * @return 判断结果，true表示无重复值，false表示有重复值
     */
    private static <T> Predicate<T> anyDistinctByKey(Function<T, Object>... functions) {
        int length = functions.length;

        // 初始化判断重复的集合
        List<Set<String>> list = Lists.newArrayListWithCapacity(length);
        for (int i = 0; i < length; i++) {
            list.add(Sets.newHashSet());
        }

        return t -> {
            // 判断是否与之前的数据的重复
            boolean existFlag = consumeLoop(functions, list, t, true, Set::contains);

            // 如果没有重复的数据，则将对应的值加入到集合中
            if (!existFlag) {
                consumeLoop(functions, list, t, false, Set::add);
            }

            return !existFlag;
        };
    }

    /**
     * 遍历Function判断条件是否成立
     *
     * @param functions   对象与成员属性的映射数组
     * @param list        存储set的集合，需与{@code functions}等长
     * @param obj         被操作的对象
     * @param trueExist   条件成立时是否退出循环
     * @param biPredicate 对集合与元素的逻辑操作
     * @return {@code biPredicate}只需一次布尔结果为true时则返回true，全为false时才返回false
     */
    private static <T> boolean consumeLoop(Function<T, Object>[] functions,
                                           List<Set<String>> list,
                                           T obj,
                                           boolean trueExist,
                                           BiPredicate<Set<String>, String> biPredicate) {
        int length = functions.length;
        boolean result = false;
        for (int i = 0; i < length; i++) {
            Function<? super T, Object> function = functions[i];
            Object property = function.apply(obj);
            if (Objects.isNull(property)) {
                continue;
            }

            String str = property.toString();
            if (StringUtils.isBlank(str)) {
                continue;
            }

            Set<String> set = list.get(i);
            if (biPredicate.test(set, str)) {
                result = true;
            }

            if (trueExist && result) {
                break;
            }
        }

        return result;
    }

    /**
     * 查找符合条件的第一个对象，如果没有符合条件的对象，则返回{@code null}
     *
     * <p>例：StreamUtils.findFirst(list, bond -> bond.getStatus().equals(bondStatus))
     *
     * @param list      集合
     * @param predicate 条件
     * @return 第一个对象
     */
    public static <T> T findFirst(List<T> list, Predicate<? super T> predicate) {
        if (CollUtil.isEmpty(list)) {
            return null;
        }
        return list.stream().filter(predicate).findFirst().orElse(null);
    }

    /**
     * 获取无重复值的集合
     *
     * @param list   集合
     * @param mapper 要返回的属性类型
     * @return 对象属性的集合
     */
    public static <T, R> List<R> convertUnique(Collection<T> list, Function<T, R> mapper) {
        if (CollUtil.isEmpty(list)) {
            return Lists.newArrayList();
        }
        return list.stream().map(mapper).distinct().collect(Collectors.toList());
    }

    /**
     * 根据指定条件分组
     *
     * @param list   源集合
     * @param mapper 映射条件
     * @param <T>    集合对象类型
     * @param <R>    映射后的Map的key类型
     * @return Map
     */
    public static <T, R> Map<R, List<T>> group(Collection<T> list, Function<T, R> mapper) {
        if (CollUtil.isEmpty(list)) {
            return Maps.newHashMap();
        }

        return list.stream().collect(Collectors.groupingBy(mapper));
    }

    /**
     * 根据指定条件对 list 分组， 并输出指定的集合
     *
     * @param list
     * @param mapper
     * @param collector
     * @param <T>
     * @param <K>
     * @param <M>
     * @return
     */
    public static <T, K, R, M> Map<K, M> groupMap(Collection<T> list,
                                                  Function<? super T, ? extends K> mapper,
                                                  Collector<T, R, M> collector) {
        if (CollectionUtils.isEmpty(list)) {
            return Maps.newHashMap();
        }

        return list.stream().collect(Collectors.groupingBy(mapper, collector));
    }


    /**
     * 根据指定条件分割
     *
     * @param list      源集合
     * @param predicate 映射条件
     * @param <T>       集合对象类型
     * @return Map
     */
    public static <T> Map<Boolean, List<T>> partition(Collection<T> list, Predicate<T> predicate) {
        if (CollUtil.isEmpty(list)) {
            return Maps.newHashMap();
        }

        return list.stream().collect(Collectors.partitioningBy(predicate));
    }

    /**
     * 通过指定条件过滤，并转换集合
     *
     * @param list      待过滤集合
     * @param predicate 过滤条件
     * @param mapper    要返回的集合类型
     * @return 已过滤集合
     */
    public static <T, R> List<R> filterAndMap(List<T> list, Predicate<T> predicate, Function<T, R> mapper) {
        if (CollUtil.isEmpty(list)) {
            return Lists.newArrayList();
        }

        return list.stream()
                .filter(predicate)
                .map(mapper)
                .collect(Collectors.toList());
    }

    public static <T> List<T> filterAndPeek(List<T> list, Predicate<T> predicate, Consumer<T> mapper) {
        if (CollUtil.isEmpty(list)) {
            return Lists.newArrayListWithCapacity(0);
        }

        return list.stream()
                .filter(predicate)
                .peek(mapper)
                .collect(Collectors.toList());
    }

    /**
     * 通过指定条件过滤，并转换集合
     *
     * @param list      待过滤集合
     * @param predicate 过滤条件
     * @param mapper    要返回的集合类型
     * @return 已过滤集合
     */
    public static <T, R> List<R> filterAndFlatMap(List<T> list, Predicate<T> predicate, Function<T, Stream<R>> mapper) {
        if (CollUtil.isEmpty(list)) {
            return Lists.newArrayList();
        }

        return list.stream()
                .filter(predicate)
                .flatMap(mapper)
                .collect(Collectors.toList());
    }

    public static <T, R> List<R> filterAndFlatMap(Collection<T> list, Predicate<T> predicate, Function<T, Stream<R>> mapper) {
        if (CollUtil.isEmpty(list)) {
            return Lists.newArrayList();
        }

        return list.stream()
                .filter(predicate)
                .flatMap(mapper)
                .collect(Collectors.toList());
    }

    public static <T, R> List<R> flatMap(Collection<T> list, Function<? super T, ? extends Stream<? extends R>> mapper) {

        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }
        return list.stream().flatMap(mapper).collect(Collectors.toList());
    }

    public static <T, R> List<R> flatMapAndDistinct(Collection<T> list, Function<? super T, ? extends Stream<? extends R>> mapper) {

        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }
        return list.stream().flatMap(mapper).distinct().collect(Collectors.toList());
    }

    /**
     * 通过指定条件过滤，并分组
     *
     * @param list      待过滤集合
     * @param predicate 过滤条件
     * @param mapper    分组逻辑
     * @return 分组后集合
     */
    public static <T, R> Map<R, T> filterAndToMap(List<T> list, Predicate<T> predicate, Function<T, R> mapper) {
        if (CollUtil.isEmpty(list)) {
            return Maps.newHashMap();
        }

        return list.stream()
                .filter(predicate)
                .collect(Collectors.toMap(mapper, Function.identity(), (o1, o2) -> o1));
    }

    public static <T, R, V> Map<R, V> filterAndToMap(List<T> list,
                                                     Predicate<T> predicate,
                                                     Function<T, R> mapper,
                                                     Function<T, V> valueMapper) {
        if (CollUtil.isEmpty(list)) {
            return Maps.newHashMap();
        }

        return list.stream()
                .filter(predicate)
                .collect(Collectors.toMap(mapper, valueMapper, (o1, o2) -> o1));
    }

    public static <K, V, RK, RV> Map<RK, RV> filterAndToMap(Map<K, V> map,
                                                            Predicate<Map.Entry<K, V>> predicate,
                                                            Function<Map.Entry<K, V>, RK> mapper,
                                                            Function<Map.Entry<K, V>, RV> valueMapper) {
        if (CollUtil.isEmpty(map)) {
            return Maps.newHashMap();
        }

        return map.entrySet()
                .stream()
                .filter(predicate)
                .collect(Collectors.toMap(mapper, valueMapper, (o1, o2) -> o1));
    }

    /**
     * 通过指定条件过滤，并分组
     *
     * @param list      待过滤集合
     * @param predicate 过滤条件
     * @param mapper    分组逻辑
     * @return 分组后集合
     */
    public static <T, R> Map<R, List<T>> filterAndGroup(List<T> list, Predicate<T> predicate, Function<T, R> mapper) {
        if (CollUtil.isEmpty(list)) {
            return Maps.newHashMap();
        }

        return list.stream()
                .filter(predicate)
                .collect(Collectors.groupingBy(mapper));
    }

    public static <T> List<T> filterAndDistinct(Collection<T> list, Predicate<T> predicate) {
        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }
        return list.stream().filter(predicate).distinct().collect(Collectors.toList());
    }

    public static <T, R> List<R> filterAndMapAndDistinct(Collection<T> list, Predicate<T> predicate, Function<T, R> mapper) {
        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }
        return list.stream().filter(predicate).map(mapper).distinct().collect(Collectors.toList());
    }

    public static <T, K, R, M> Map<K, M> filterAndGroupMap(Collection<T> list,
                                                           Predicate<T> predicate,
                                                           Function<? super T, ? extends K> mapper,
                                                           Collector<T, R, M> collector) {
        if (CollectionUtils.isEmpty(list)) {
            return Maps.newHashMap();
        }

        return list.stream().filter(predicate).collect(Collectors.groupingBy(mapper, collector));
    }

    /**
     * 任一元素匹配
     *
     * @param list      集合
     * @param predicate 匹配条件
     * @return 匹配结果
     */
    public static <T> boolean anyMatch(Collection<T> list, Predicate<T> predicate) {
        if (CollUtil.isEmpty(list)) {
            return false;
        }

        return list.stream()
                .anyMatch(predicate);
    }

    /**
     * 全部元素匹配
     *
     * @param list      待过滤集合
     * @param predicate 匹配条件
     * @return 匹配结果
     */
    public static <T> boolean allMatch(List<T> list, Predicate<T> predicate) {
        if (CollUtil.isEmpty(list)) {
            return false;
        }

        return list.stream()
                .allMatch(predicate);
    }

    /**
     * 获取转换后的集合
     *
     * @param list   源集合
     * @param mapper 要返回的集合类型
     * @return 结果集
     */
    public static <T, R> List<R> map(Collection<T> list, Function<T, R> mapper) {
        if (CollUtil.isEmpty(list)) {
            return Lists.newArrayList();
        }
        return list.stream().map(mapper).collect(Collectors.toList());
    }

    /**
     * 获取转换后的集合
     *
     * @param list   源集合
     * @param mapper 要返回的集合类型
     * @return 结果集set
     */
    public static <T, R> Set<R> map2Set(Collection<T> list, Function<T, R> mapper) {
        if (CollUtil.isEmpty(list)) {
            return Sets.newHashSet();
        }
        return list.stream().map(mapper).collect(Collectors.toSet());
    }


    /**
     * 通过指定条件过滤，并转换集合
     *
     * @param list      待过滤集合
     * @param predicate 过滤条件
     * @param mapper    要返回的集合类型
     * @return 已过滤集合
     */
    public static <T, R> Set<R> mapAndFilter2Set(Collection<T> list, Function<T, R> mapper, Predicate<R> predicate) {
        if (CollUtil.isEmpty(list)) {
            return Sets.newHashSet();
        }

        return list.stream()
                .map(mapper)
                .filter(predicate)
                .collect(Collectors.toSet());
    }

    /**
     * 排序
     *
     * @param list
     * @param mapper
     * @param sortMapper
     * @param reverse1
     * @param <K>
     * @param <T>
     * @param <U>
     * @return
     */
    public static <K, T, U extends Comparable<? super U>> List<T> mapAndSort(Collection<K> list, Function<K, T> mapper, Function<? super T, ? extends U> sortMapper, boolean reverse1) {
        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }

        Comparator<T> comparing = Comparator.comparing(sortMapper);

        if (reverse1) {
            comparing = comparing.reversed();
        }

        return list.stream().map(mapper).sorted(comparing).collect(Collectors.toList());
    }

    /**
     * 拼音排序
     *
     * @param list
     * @param mapper
     * @param sortMapper
     * @param reverse1
     * @param <K>
     * @param <T>
     * @param <U>
     * @return
     */
    public static <K, T, U extends Comparable<? super U>> List<T> mapAndSortPinYin(Collection<K> list, Function<K, T> mapper, Function<? super T, String> sortMapper, boolean reverse1) {
        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }
        PinyinComparator pinyinComparator = new PinyinComparator();
        Comparator<T> comparing = Comparator.comparing(sortMapper, pinyinComparator);
        if (reverse1) {
            comparing = comparing.reversed();
        }
        return list.stream().map(mapper).sorted(comparing).collect(Collectors.toList());
    }

    public static <T> List<T> peek(List<T> list, Consumer<? super T> action) {
        if (CollUtil.isEmpty(list)) {
            return Lists.newArrayList();
        }

        return list.stream()
                .peek(action)
                .collect(Collectors.toList());
    }

    /**
     * 获取转换并去除后的集合
     *
     * @param list   源集合
     * @param mapper 要返回的集合类型
     * @return 结果集
     */
    public static <T, R> List<R> mapAndDistinct(Collection<T> list, Function<T, R> mapper) {
        if (CollUtil.isEmpty(list)) {
            return Lists.newArrayList();
        }
        return list.stream().map(mapper).distinct().collect(Collectors.toList());
    }

    /**
     * 合并字段
     *
     * @param list        集合
     * @param mapper      要合并的字段
     * @param joinContent 分隔符
     * @return 合并结果
     */
    public static <T> String join(List<T> list,
                                  Function<T, ? extends CharSequence> mapper,
                                  CharSequence joinContent) {
        if (CollUtil.isEmpty(list)) {
            return "";
        }

        return list.stream()
                .map(mapper)
                .collect(Collectors.joining(joinContent));
    }

    /**
     * 通过指定条件过滤，并合并字段
     *
     * @param list        集合
     * @param predicate   过滤条件
     * @param mapper      要合并的字段
     * @param joinContent 分隔符
     * @return 合并结果
     */
    public static <T> String filterAndJoin(List<T> list,
                                           Predicate<T> predicate,
                                           Function<T, ? extends CharSequence> mapper,
                                           CharSequence joinContent) {
        if (CollUtil.isEmpty(list)) {
            return "";
        }

        return list.stream()
                .filter(predicate)
                .map(mapper)
                .collect(Collectors.joining(joinContent));
    }

    /**
     * 累加值
     *
     * @param list     集合
     * @param function 需累加的值
     * @param <T>      值类型
     * @return 累加结果
     */
    public static <T> BigDecimal sum(List<T> list, Function<T, BigDecimal> function) {
        if (CollUtil.isEmpty(list)) {
            return BigDecimal.ZERO;
        }

        return list.stream()
                .map(function)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    public static <T> Integer sumInt(List<T> list, Function<T, Integer> function) {
        if (CollUtil.isEmpty(list)) {
            return 0;
        }


        return list.stream()
                .map(function)
                .reduce(0, Integer::sum);

    }

    /**
     * 通过指定条件过滤，并累加值
     *
     * @param list      集合
     * @param predicate 过滤条件
     * @param function  需累加的值
     * @param <T>       值类型
     * @return 累加结果
     */
    public static <T> BigDecimal filterAndSum(List<T> list, Predicate<T> predicate, Function<T, BigDecimal> function) {
        if (CollUtil.isEmpty(list)) {

            return BigDecimal.ZERO;
        }

        return list.stream()
                .filter(predicate)
                .map(function)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 通过指定条件过滤并排序
     *
     * @param list       待处理集合
     * @param predicate  过滤条件
     * @param comparator 排序方式
     * @return 已过滤集合
     */
    public static <T> List<T> filterAndSorted(List<T> list, Predicate<T> predicate, Comparator<T> comparator) {
        if (CollUtil.isEmpty(list)) {
            return Lists.newArrayList();
        }

        return list.stream()
                .filter(predicate)
                .sorted(comparator)
                .collect(Collectors.toList());
    }

    /**
     * 通过指定条件过滤并计数
     *
     * @param list      待处理集合
     * @param predicate 过滤条件
     * @return 数量
     */
    public static <T> long filterAndCount(List<T> list, Predicate<T> predicate) {
        if (CollUtil.isEmpty(list)) {
            return 0L;
        }

        return list.stream()
                .filter(predicate)
                .count();
    }

    /**
     * 过滤后再对流进行操作
     *
     * @param list      待处理集合
     * @param predicate 过滤条件
     * @param finisher  过滤后的后续操作
     * @param <T>       T
     * @param <R>       result
     * @return R
     */
    public static <T, R> R filterThen(List<T> list, Predicate<T> predicate, Function<Stream<T>, R> finisher) {
        if (CollectionUtils.isEmpty(list) || Objects.isNull(finisher)) {
            return null;
        }

        Stream<T> stream = list.stream()
                .filter(predicate);

        return finisher.apply(stream);

    }

    /**
     * 将values转换为List
     *
     * @param mapper mapper
     * @param values values
     * @param <T>    T
     * @param <R>    R
     * @return list
     */
    public static <T, R> List<R> of(Function<T, R> mapper, T... values) {
        return Stream.of(values)
                .map(mapper)
                .collect(Collectors.toList());
    }


    /**
     * 排序
     *
     * @param list       list
     * @param comparator comparator
     * @param <T>        T
     * @return list
     */
    public static <T> List<T> sorted(List<T> list, Comparator<T> comparator) {
        if (CollUtil.isEmpty(list)) {
            return Lists.newArrayList();
        }

        return list.stream()
                .sorted(comparator)
                .collect(Collectors.toList());
    }

    public static <K, V, RK, RV> Map<RK, RV> map(Map<K, V> map,
                                                 Function<? super Map.Entry<K, V>, ? extends RK> keyMapper,
                                                 Function<? super Map.Entry<K, V>, ? extends RV> valueMapper) {


        if (CollUtil.isEmpty(map)) {
            return Maps.newHashMap();
        }

        return map.entrySet()
                .stream()
                .collect(Collectors.toMap(keyMapper, valueMapper));

    }

    public static <K, V, RK> Map<RK, V> map(Map<K, V> map,
                                            Function<? super Map.Entry<K, V>, ? extends RK> keyMapper) {


        if (CollUtil.isEmpty(map)) {
            return Maps.newHashMap();
        }

        return map.entrySet()
                .stream()
                .collect(Collectors.toMap(keyMapper, Map.Entry::getValue));

    }

}
